/**
 *
 */
package com.xbang.core.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.security.util.FieldUtils;

/**
 * Simple utility class for working with the reflection API and handling
 * reflection exceptions.
 * 
 * 
 * @author dev.zhang
 * @author Carl
 */
public abstract class ReflectionUtils {

	/**
	 * 得到字段类型
	 * 
	 * @param clazz
	 * @param fieldName
	 * @return
	 */
	public static Class getFieldType(Class clazz, String fieldName) {
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.getName().equals(fieldName)) {
				return field.getClass();
			}
		}
		return null;
	}

	public static Field getFieldType(Class clazz, String properties, Map<String, Class<?>> clazzs) {
		Field field = null;
		if (!properties.isEmpty()) {
			String[] fields = properties.split("\\.");
			for (int index = 0; index < fields.length; index++) {
				field = getSignFieldType(clazz, fields[index], clazzs);
				if (index < fields.length - 1) {
					clazz = field.getType();
				}
			}
		}

		return field;
	}

	public static Field getSignFieldType(Class clazz, String property, Map<String, Class<?>> clazzs) {

		Field field = FieldUtils.getField(clazz, property);

		return field;
	}

	/**
	 * @param owner
	 * @param methodName
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public static Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {

		Class ownerClass = owner.getClass();

		Class[] argsClass = new Class[args.length];

		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}

		Method method = ownerClass.getMethod(methodName, argsClass);

		return method.invoke(owner, args);
	}

	public static void setFeildByApacheCheckString(Object object, String fieldName, Object value) throws IllegalAccessException, InvocationTargetException,
			SecurityException, NoSuchFieldException {
		Class clazz = object.getClass();
		Field field = clazz.getDeclaredField(fieldName);
		if (field.getType().toString().equals(String.class.toString())) {
			value = parseString(value);
		}
		BeanUtils.setProperty(object, fieldName, value);
	}

	public static String parseString(Object object) {
		if (object == null) {
			return null;
		}
		String tmpString = object.toString();
		if (!(object instanceof String)) {
			if (tmpString.contains("E")) {
				Double doubles = Double.valueOf(tmpString);
				tmpString = "" + doubles.longValue();
			} else if (tmpString.contains(".")) {
				tmpString = tmpString.split("\\.")[0];
			}
		}
		return tmpString;
	}

	public static void setFeildByApache(Object object, String fieldName, Object value) throws IllegalAccessException, InvocationTargetException {
		BeanUtils.setProperty(object, fieldName, value);
	}

	public static void setField(Object object, String fieldName, Object value) throws SecurityException, NoSuchFieldException {
		Class clazz = object.getClass();
		Field field = null;
		try {
			field = clazz.getDeclaredField(fieldName);
		} catch (Exception e) {
			field = clazz.getField(fieldName);
		}
		if (field != null) {
			setField(field, object, value);
		}

	}

	/**
	 * Simply create a new instance of a Class, assume that the class has the
	 * default constructor
	 * 
	 * @param clazz
	 * @return
	 */
	public static Object newInstance(Class<?> clazz) {
		try {
			return clazz.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Do a wrap for
	 * org.springframework.util.ReflectionUtils#makeAccessible(Field)
	 * 
	 * @param field
	 * @see org.springframework.util.ReflectionUtils#makeAccessible(Field)
	 */
	public static void makeAccessible(Field field) {
		org.springframework.util.ReflectionUtils.makeAccessible(field);
	}

	/**
	 * Set field value and do a wrap for
	 * {@link org.springframework.util.ReflectionUtils#setField(Field, Object, Object)}
	 * 
	 * @param field
	 * @param target
	 * @param value
	 * @see org.springframework.util.ReflectionUtils#setField(Field, Object,
	 *      Object)
	 */
	public static void setField(Field field, Object target, Object value) {

		org.springframework.util.ReflectionUtils.setField(field, target, value);
	}

	/**
	 * Set the field represented by the supplied field object on the specified
	 * target object to the specified value. Autobox value when the field is
	 * primitive type.
	 * 
	 * @param field
	 * @param target
	 * @param value
	 */
	public static void setField(Field field, Object target, String value) {
		ReflectionUtils.makeAccessible(field);
		Class<?> type = field.getType();
		if (String.class.equals(type)) {
			try {
				field.set(target, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		} else {
			Object convertedValue = TypeConverterUtils.parse(value, type);
			org.springframework.util.ReflectionUtils.setField(field, target, convertedValue);
		}
	}

	public static void main(String[] args) {
		String test = "1.3801966334E10";
		Double doubles = Double.valueOf(test).doubleValue();
		doubles.toString();
		System.out.println(doubles + " -------" + doubles.longValue());
	}

}
